namespace OpenRiaServices.Issue92.Web.Migrations
{
    using System.Collections.Generic;
    using System.Configuration;
    using System.Data;
    using System.Data.Entity.Migrations;
    using System.Data.SqlClient;
    using System.Linq;
    using FastMember;
    using Models;

    internal sealed class Configuration : DbMigrationsConfiguration<OpenRiaServices.Issue92.Web.Models.Issue92Context>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = false;
        }

        protected override void Seed(OpenRiaServices.Issue92.Web.Models.Issue92Context context)
        {
            //  This method will be called after migrating to the latest version.

            bool deleteData = false;
            var currentNumberOfParents = context.ParentEntities.Count();

            int numberOfParentMocks;
            if (!int.TryParse(ConfigurationManager.AppSettings["NumberOfParentMocks"], out numberOfParentMocks))
            {
                numberOfParentMocks = 100;
            }

            int numberOfChildMocksPerParent;
            if (!int.TryParse(ConfigurationManager.AppSettings["NumberOfChildMocksPerParent"], out numberOfChildMocksPerParent))
            {
                numberOfChildMocksPerParent = 1000;
            }

            if (currentNumberOfParents != numberOfParentMocks)
            {
                deleteData = true;
            }

            if (!deleteData)
            {
                var currentMaxNumberOfChildMocks = context.ChildEntities
                    .GroupBy(e => e.ParentEntityId)
                    .OrderByDescending(e => e.Count())
                    .FirstOrDefault();
                var currentMinNumberOfChildMocks = context.ChildEntities
                    .GroupBy(e => e.ParentEntityId)
                    .OrderByDescending(e => e.Count())
                    .FirstOrDefault();
                if (currentMaxNumberOfChildMocks == null || currentMinNumberOfChildMocks == null || (currentMaxNumberOfChildMocks.Count() != numberOfChildMocksPerParent && currentMinNumberOfChildMocks.Count() != numberOfChildMocksPerParent))
                {
                    deleteData = true;
                }
            }

            if (deleteData)
            {
                var parentEntities = context.ParentEntities.ToList();
                foreach (var parentEntity in parentEntities)
                {
                    context.ParentEntities.Remove(parentEntity);
                }

                context.SaveChanges();

                for (int i = 0; i < numberOfParentMocks; i++)
                {
                    var parentEntity = new ParentEntity()
                    {
                        Name = string.Format("Parent Mock {0}", (i + 1).ToString())
                    };
                    context.ParentEntities.Add(parentEntity);

                    //for (int j = 0; j < numberOfChildMocksPerParent; j++)
                    //{
                    //    var childEntity = new ChildEntity()
                    //    {
                    //        Name = string.Format("Child Mock {0}_{1}", (i + 1).ToString(), (j + 1).ToString())
                    //    };
                    //    parentEntity.ChildEntities.Add(childEntity);
                    //}
                }

                context.SaveChanges();

                var childEntities = new List<ChildEntity>();
                foreach (var parent in context.ParentEntities.Local)
                {
                    for (int i = 0; i < numberOfChildMocksPerParent; i++)
                    {
                        var childEntity = new ChildEntity()
                        {
                            Name = string.Format("Child Mock {0}_{1}", parent.Id.ToString(), (i + 1).ToString()),
                            ParentEntityId = parent.Id
                        };
                        childEntities.Add(childEntity);
                    }
                }

                if (context.Database.Connection.State == ConnectionState.Closed)
                {
                    context.Database.Connection.Open();
                }

                var transaction = context.Database.CurrentTransaction != null ? (SqlTransaction)context.Database.CurrentTransaction.UnderlyingTransaction : null;
                using (SqlBulkCopy bulkCopy = new SqlBulkCopy(
                    (SqlConnection)context.Database.Connection,
                    SqlBulkCopyOptions.CheckConstraints | SqlBulkCopyOptions.FireTriggers,
                    transaction))
                {
                    bulkCopy.ColumnMappings.Add(new SqlBulkCopyColumnMapping("Name", "Name"));
                    bulkCopy.ColumnMappings.Add(new SqlBulkCopyColumnMapping("ParentEntityId", "ParentEntityId"));

                    using (var reader = ObjectReader.Create(childEntities, "Name", "ParentEntityId"))
                    {
                        bulkCopy.BatchSize = 10000;
                        bulkCopy.DestinationTableName = "ChildEntities";
                        bulkCopy.BulkCopyTimeout = 1800;
                        bulkCopy.WriteToServer(reader);
                    }
                }
            }
        }
    }
}
